home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_006 / microemacs / buffer.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  13KB  |  364 lines

  1. /*
  2.  * Buffer management.
  3.  * Some of the functions are internal,
  4.  * and some are actually attached to user
  5.  * keys. Like everyone else, they set hints
  6.  * for the display system.
  7.  */
  8. #include        <stdio.h>
  9. #include        "ed.h"
  10.  
  11. /*
  12.  * Attach a buffer to a window. The
  13.  * values of dot and mark come from the buffer
  14.  * if the use count is 0. Otherwise, they come
  15.  * from some other window.
  16.  */
  17. usebuffer(f, n)
  18. {
  19.         register BUFFER *bp;
  20.         register WINDOW *wp;
  21.         register int    s;
  22.         char            bufn[NBUFN];
  23.  
  24.         if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  25.                 return (s);
  26.         if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  27.                 return (FALSE);
  28.         if (--curbp->b_nwnd == 0) {             /* Last use.            */
  29.                 curbp->b_dotp  = curwp->w_dotp;
  30.                 curbp->b_doto  = curwp->w_doto;
  31.                 curbp->b_markp = curwp->w_markp;
  32.                 curbp->b_marko = curwp->w_marko;
  33.         }
  34.         curbp = bp;                             /* Switch.              */
  35.         curwp->w_bufp  = bp;
  36.         curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  37.         curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  38.         if (bp->b_nwnd++ == 0) {                /* First use.           */
  39.                 curwp->w_dotp  = bp->b_dotp;
  40.                 curwp->w_doto  = bp->b_doto;
  41.                 curwp->w_markp = bp->b_markp;
  42.                 curwp->w_marko = bp->b_marko;
  43.                 return (TRUE);
  44.         }
  45.         wp = wheadp;                            /* Look for old.        */
  46.         while (wp != NULL) {
  47.                 if (wp!=curwp && wp->w_bufp==bp) {
  48.                         curwp->w_dotp  = wp->w_dotp;
  49.                         curwp->w_doto  = wp->w_doto;
  50.                         curwp->w_markp = wp->w_markp;
  51.                         curwp->w_marko = wp->w_marko;
  52.                         break;
  53.                 }
  54.                 wp = wp->w_wndp;
  55.         }
  56.         return (TRUE);
  57. }
  58.  
  59. /*
  60.  * Dispose of a buffer, by name.
  61.  * Ask for the name. Look it up (don't get too
  62.  * upset if it isn't there at all!). Get quite upset
  63.  * if the buffer is being displayed. Clear the buffer (ask
  64.  * if the buffer has been changed). Then free the header
  65.  * line and the buffer header. Bound to "C-X K".
  66.  */
  67. killbuffer(f, n)
  68. {
  69.         register BUFFER *bp;
  70.         register BUFFER *bp1;
  71.         register BUFFER *bp2;
  72.         register int    s;
  73.         char            bufn[NBUFN];
  74.  
  75.         if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  76.                 return (s);
  77.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  78.                 return (TRUE);
  79.         if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  80.                 mlwrite("Buffer is being displayed");
  81.                 return (FALSE);
  82.         }
  83.         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  84.                 return (s);
  85.         free((char *) bp->b_linep);             /* Release header line. */
  86.         bp1 = NULL;                             /* Find the header.     */
  87.         bp2 = bheadp;
  88.         while (bp2 != bp) {
  89.                 bp1 = bp2;
  90.                 bp2 = bp2->b_bufp;
  91.         }
  92.         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  93.         if (bp1 == NULL)                        /* Unlink it.           */
  94.                 bheadp = bp2;
  95.         else
  96.                 bp1->b_bufp = bp2;
  97.         free((char *) bp);                      /* Release buffer block */
  98.         return (TRUE);
  99. }
  100.  
  101. /*
  102.  * List all of the active
  103.  * buffers. First update the special
  104.  * buffer that holds the list. Next make
  105.  * sure at least 1 window is displaying the
  106.  * buffer list, splitting the screen if this
  107.  * is what it takes. Lastly, repaint all of
  108.  * the windows that are displaying the
  109.  * list. Bound to "C-X C-B".
  110.  */
  111. listbuffers(f, n)
  112. {
  113.         register WINDOW *wp;
  114.         register BUFFER *bp;
  115.         register int    s;
  116.  
  117.         if ((s=makelist()) != TRUE)
  118.                 return (s);
  119.         if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  120.                 if ((wp=wpopup()) == NULL)
  121.                         return (FALSE);
  122.                 bp = wp->w_bufp;
  123.                 if (--bp->b_nwnd == 0) {
  124.                         bp->b_dotp  = wp->w_dotp;
  125.                         bp->b_doto  = wp->w_doto;
  126.                         bp->b_markp = wp->w_markp;
  127.                         bp->b_marko = wp->w_marko;
  128.                 }
  129.                 wp->w_bufp  = blistp;
  130.                 ++blistp->b_nwnd;
  131.         }
  132.         wp = wheadp;
  133.         while (wp != NULL) {
  134.                 if (wp->w_bufp == blistp) {
  135.                         wp->w_linep = lforw(blistp->b_linep);
  136.                         wp->w_dotp  = lforw(blistp->b_linep);
  137.                         wp->w_doto  = 0;
  138.                         wp->w_markp = NULL;
  139.                         wp->w_marko = 0;
  140.                         wp->w_flag |= WFMODE|WFHARD;
  141.                 }
  142.                 wp = wp->w_wndp;
  143.         }
  144.         return (TRUE);
  145. }
  146.  
  147. /*
  148.  * This routine rebuilds the
  149.  * text in the special secret buffer
  150.  * that holds the buffer list. It is called
  151.  * by the list buffers command. Return TRUE
  152.  * if everything works. Return FALSE if there
  153.  * is an error (if there is no memory).
  154.  */
  155. makelist()
  156. {
  157.         register char   *cp1;
  158.         register char   *cp2;
  159.         register int    c;
  160.         register BUFFER *bp;
  161.         register LINE   *lp;
  162.         register int    nbytes;
  163.         register int    s;
  164.         register int    type;
  165.         char            b[6+1];
  166.         char            line[128];
  167.  
  168.         blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  169.         if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  170.                 return (s);
  171.         strcpy(blistp->b_fname, "");
  172.         if (addline("C   Size Buffer           File") == FALSE
  173.         ||  addline("-   ---- ------           ----") == FALSE)
  174.                 return (FALSE);
  175.         bp = bheadp;                            /* For all buffers      */
  176.         while (bp != NULL) {
  177.                 if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones.     */
  178.                         bp = bp->b_bufp;
  179.                         continue;
  180.                 }
  181.                 cp1 = &line[0];                 /* Start at left edge   */
  182.                 if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  183.                         *cp1++ = '*';
  184.                 else
  185.                         *cp1++ = ' ';
  186.                 *cp1++ = ' ';                   /* Gap.                 */
  187.                 nbytes = 0;                     /* Count bytes in buf.  */
  188.                 lp = lforw(bp->b_linep);
  189.                 while (lp != bp->b_linep) {
  190.                         nbytes += llength(lp)+1;
  191.                         lp = lforw(lp);
  192.                 }
  193.                 itoa(b, 6, nbytes);             /* 6 digit buffer size. */
  194.                 cp2 = &b[0];
  195.                 while ((c = *cp2++) != 0)
  196.                         *cp1++ = c;
  197.                 *cp1++ = ' ';                   /* Gap.                 */
  198.                 cp2 = &bp->b_bname[0];          /* Buffer name          */
  199.                 while ((c = *cp2++) != 0)
  200.                         *cp1++ = c;
  201.                 cp2 = &bp->b_fname[0];          /* File name            */
  202.                 if (*cp2 != 0) {
  203.                         while (cp1 < &line[1+1+6+1+NBUFN+1])
  204.                                 *cp1++ = ' ';           
  205.                         while ((c = *cp2++) != 0) {
  206.                                 if (cp1 < &line[128-1])
  207.                                         *cp1++ = c;
  208.                         }
  209.                 }
  210.                 *cp1 = 0;                       /* Add to the buffer.   */
  211.                 if (addline(line) == FALSE)
  212.                         return (FALSE);
  213.                 bp = bp->b_bufp;
  214.         }
  215.         return (TRUE);                          /* All done             */
  216. }
  217.  
  218. itoa(buf, width, num)
  219. register char   buf[];
  220. register int    width;
  221. register int    num;
  222. {
  223.         buf[width] = 0;                         /* End of string.       */
  224.         while (num >= 10) {                     /* Conditional digits.  */
  225.                 buf[--width] = (num%10) + '0';
  226.                 num /= 10;
  227.         }
  228.         buf[--width] = num + '0';               /* Always 1 digit.      */
  229.         while (width != 0)                      /* Pad with blanks.     */
  230.                 buf[--width] = ' ';
  231. }
  232.  
  233. /*
  234.  * The argument "text" points to
  235.  * a string. Append this line to the
  236.  * buffer list buffer. Handcraft the EOL
  237.  * on the end. Return TRUE if it worked and
  238.  * FALSE if you ran out of room.
  239.  */
  240. addline(text)
  241. char    *text;
  242. {
  243.         register LINE   *lp;
  244.         register int    i;
  245.         register int    ntext;
  246.  
  247.         ntext = strlen(text);
  248.         if ((lp=lalloc(ntext)) == NULL)
  249.                 return (FALSE);
  250.         for (i=0; i<ntext; ++i)
  251.                 lputc(lp, i, text[i]);
  252.         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  253.         lp->l_bp = blistp->b_linep->l_bp;
  254.         blistp->b_linep->l_bp = lp;
  255.         lp->l_fp = blistp->b_linep;
  256.         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  257.                 blistp->b_dotp = lp;            /* move it to new line  */
  258.         return (TRUE);
  259. }
  260.  
  261. /*
  262.  * Look through the list of
  263.  * buffers. Return TRUE if there
  264.  * are any changed buffers. Buffers
  265.  * that hold magic internal stuff are
  266.  * not considered; who cares if the
  267.  * list of buffer names is hacked.
  268.  * Return FALSE if no buffers
  269.  * have been changed.
  270.  */
  271. anycb()
  272. {
  273.         register BUFFER *bp;
  274.  
  275.         bp = bheadp;
  276.         while (bp != NULL) {
  277.                 if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
  278.                         return (TRUE);
  279.                 bp = bp->b_bufp;
  280.         }
  281.         return (FALSE);
  282. }
  283.  
  284. /*
  285.  * Find a buffer, by name. Return a pointer
  286.  * to the BUFFER structure associated with it. If
  287.  * the named buffer is found, but is a TEMP buffer (like
  288.  * the buffer list) conplain. If the buffer is not found
  289.  * and the "cflag" is TRUE, create it. The "bflag" is
  290.  * the settings for the flags in in buffer.
  291.  */
  292. BUFFER  *
  293. bfind(bname, cflag, bflag)
  294. register char   *bname;
  295. {
  296.         register BUFFER *bp;
  297.         register LINE   *lp;
  298.  
  299.         bp = bheadp;
  300.         while (bp != NULL) {
  301.                 if (strcmp(bname, bp->b_bname) == 0) {
  302.                         if ((bp->b_flag&BFTEMP) != 0) {
  303.                                 mlwrite("Cannot select builtin buffer");
  304.                                 return (NULL);
  305.                         }
  306.                         return (bp);
  307.                 }
  308.                 bp = bp->b_bufp;
  309.         }
  310.         if (cflag != FALSE) {
  311.                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  312.                         return (NULL);
  313.                 if ((lp=lalloc(0)) == NULL) {
  314.                         free((char *) bp);
  315.                         return (NULL);
  316.                 }
  317.                 bp->b_bufp  = bheadp;
  318.                 bheadp = bp;
  319.                 bp->b_dotp  = lp;
  320.                 bp->b_doto  = 0;
  321.                 bp->b_markp = NULL;
  322.                 bp->b_marko = 0;
  323.                 bp->b_flag  = bflag;
  324.                 bp->b_nwnd  = 0;
  325.                 bp->b_linep = lp;
  326.                 strcpy(bp->b_fname, "");
  327.                 strcpy(bp->b_bname, bname);
  328.                 lp->l_fp = lp;
  329.                 lp->l_bp = lp;
  330.         }
  331.         return (bp);
  332. }
  333.  
  334. /*
  335.  * This routine blows away all of the text
  336.  * in a buffer. If the buffer is marked as changed
  337.  * then we ask if it is ok to blow it away; this is
  338.  * to save the user the grief of losing text. The
  339.  * window chain is nearly always wrong if this gets
  340.  * called; the caller must arrange for the updates
  341.  * that are required. Return TRUE if everything
  342.  * looks good.
  343.  */
  344. bclear(bp)
  345. register BUFFER *bp;
  346. {
  347.         register LINE   *lp;
  348.         register int    s;
  349.         
  350.         if ((bp->b_flag&BFTEMP) == 0            /* Not scratch buffer.  */
  351.         && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  352.         && (s=mlyesno("Discard changes")) != TRUE)
  353.                 return (s);
  354.         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  355.         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  356.                 lfree(lp);
  357.         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  358.         bp->b_doto  = 0;
  359.         bp->b_markp = NULL;                     /* Invalidate "mark"    */
  360.         bp->b_marko = 0;
  361.         return (TRUE);
  362. }
  363.  
  364.